#include "TumorDriverIncludes.h"
#include <ctime>
bool CreateInitialProgramMessage( void );

#define DriverProgram_Version "0.21"
#define Program_Version "Oct. 1, 2007 at 12:01am U.S. Central Time"

#ifndef TumorGrowth_Version 
#define TumorGrowth_Version "Warning: Should be defined in tumor module!"
#endif

#ifndef Angio_Version 
#define Angio_Version "Warning: Should be defined in angio module!"
#endif

#ifdef _MSC_VER
#ifndef __COMPILER__
#define __COMPILER__ "Microsoft Visual Studio (boo!)"
#endif
#endif

#ifdef __BCPLUSPLUS__
#ifndef __COMPILER__
#define __COMPILER__ "Borland (Even worse than Microsoft! Get MinGW!)"
#endif
#endif

#ifdef __MINGW32__
#ifndef __COMPILER__
#define __COMPILER__ "MinGW Windows port of GNU g++"
#endif
#endif

#ifdef __GNUC__
#ifndef __COMPILER__
#define __COMPILER__ "GNU g++"
#endif
#endif 

#ifdef __INTEL_COMPILER
#ifndef __COMPILER__
#define __COMPILER__ "Intel icc"
#endif
#endif

int main( int argc, char* argv[] )
{
 int i,j;
 

 srand(time(0));

 long custom_seed = (long) RetrieveDoubleParameter(ParameterFile,"custom_seed"); 
 SeedRandom( custom_seed );
 
 InitializeLogfileInternals();
 StringBuffer = new char [StringBufferLength];
 StringBuffer[0] = '\0';
 
 BuildGlobalVariableList();
 DisplayGlobalVariableList();
 InitializeSaveListFromXML("save_list.xml");
 
 RUNTIME_TIC();
 
 // 0: write log file
 
 CreateInitialProgramMessage();
 cout << StringBuffer; 
 MakeLogEntry( LogFile, StringBuffer ); 

 sprintf( StringBuffer, "Using random seed %i in random.cpp.\n" , TellRandomSeed() );
 cout << StringBuffer << endl;
 MakeLogEntry( LogFile , StringBuffer );

// getchar();
/*
 // 1: filenames:
 RetrieveStringParameter( ParameterFile , "SaveDirectory" ,SaveDirectory );
 ResumeFromPreviousData = (bool) RetrieveDoubleParameter( ParameterFile, "ResumeFromPreviousData" );
 InitializeFromPicture = (bool) RetrieveDoubleParameter( ParameterFile, "InitializeFromPicture" );
 ScratchSpaceMode = (bool) RetrieveDoubleParameter( ParameterFile, "ScratchSpaceMode" );
*/ 
 
 // 2a: initialis/ze common data: TAF, ECM, and MDE for now
 
 if( !InitializeTumorGrowth() )
 {
  StartStringBuffer( "Error: Could not initialize all tumor growth data and parameter!\n" );
  cout << StringBuffer << endl;
  MakeLogEntry( LogFile , StringBuffer );
    
  return -1;
 }
//getchar();
 
 // 2c: Initialize tumor growth data and parameters; 
 

 extern bool FlowBegin; 
   extern bool AdaptionBegin;
   extern bool TumorBegin;
   ofstream Area_Output;
   ofstream WaterP;
   ofstream VesselP;
   ofstream HomP;

 // 3: main loops 
 while( t <= 0.0 + 1e-6 )
 {
  cout << "Current time: " << t << " of " << SimulationEndTime << endl;
	
   
    if(t>=0)
  {FlowBegin = 1;}
    if(t>=0.0)
  {AdaptionBegin = 1;}
  
  
  
     
  // solve for oxygen 

	 if( fabs( t - NextOutputTime ) < 1e-6 || fabs( t ) < 1e-6 )
	 {
		 cout << "Saving data ... " << endl;
		 t = NextOutputTime;
		 
		 WriteTumorConfigurationFile( t );
		 SaveTumorData( t );
		 SaveVariables(SaveDirectory,t);
		 
		 NextOutputTime += OutputInterval;
	 }
	 

  

  TIC();
  UpdateGlobalTAF();
  TOC();
  cout << StopwatchValue() << " seconds for TAF update" << endl;


  TIC();
 // cout << "FlowBegin: " << FlowBegin << endl;
  //getchar();
  UpdateAngiogenesis();
  TOC();
  
  cout << StopwatchValue() << " seconds for angiogenesis update" << endl;

  // advect tumor, save resume data, and update time
  
  TIC();
  UpdateOxygen();
  TOC();
  cout << StopwatchValue() << " seconds for oxygen update " << endl;
  
  TIC();
  dt= 0.05;
 // dt = AdvectTumor();

  //SaveResumeTumorData();
  //Save_Angio_Resume_Data();
    // reinitialize levelsets
  
  t += dt;
  TOC();
  cout << StopwatchValue() << " seconds for tumor advection" << endl;
    
  // update the TAF

  SaveVariables(SaveDirectory);
  WriteResumeTumorConfigurationFile();
	 
  
  // make a quick snapshot

  QuickPlot();
 }

 while( t <= SimulationEndTime + 1e-6 )
 {
  cout << "Current time: " << t << " of " << SimulationEndTime << endl;
	extern bool FlowBegin; 
   extern bool AdaptionBegin;


  // update angiogenesis
    if(t>=0.0)
  {FlowBegin = 1;}
    if(t>=0.0)
  {AdaptionBegin = 1;}
  
  TumorBegin = 1;
  
  
  // reinitialize levelsets
     
  // solve for oxygen 
/**
  TIC();
  UpdateOxygen();
  TOC();
  cout << StopwatchValue() << " seconds for oxygen update " << endl;
 ***/ 
  // update the microenvironment 
  // This updates: ECM, MDE, and MDEdiffusivity


  
  // solve for pressure
//if(t<=0.05)
{
  TIC();
  UpdateAngiogenesis();
  TOC();
  cout << StopwatchValue() << " seconds for angiogenesis update" << endl;
}  
  
  TIC();
  UpdateMicroenvironment();
  TOC();
  cout <<  StopwatchValue() << " seconds for microenvironment update" << endl;
	 
	// TIC();
	 //UpdateOxyWTPressure();
	 //TOC();
	 //cout << StopwatchValue() << " seconds for pressure update" << endl;	 
	 
  
	 
	 
	  // advect tumor, save resume data, and update time
	 while( t< (NextOutputTime - 1e-6) )
	 {
	 // update the speeds and prepare to advect the tumor boundaries
	 TIC();
	 ConstructVelocities();
	 TOC();
	 cout << StopwatchValue() << " seconds for velocity construction" << endl;
	 
	 
	 
	 TIC();
	 dt = AdvectTumor();
	 
	 //SaveResumeTumorData();
	 //Save_Angio_Resume_Data();
	 //SaveVariables(SaveDirectory);
	 //WriteResumeTumorConfigurationFile();
	 
	 t += dt;
	 TOC();
	 cout << StopwatchValue() << " seconds for tumor advection" << endl;
	 
	 // make a quick snapshot
	 
	 TIC();
	 Phi = Reinit( Phi );
		 UpdateNecrosisLevelset();
		 
		 UpdateQuiescentLevelset();		
	 GenerateGeometricGlobals( X,Y,Phi );
	 TOC();
	 cout << StopwatchValue() << " seconds for level set and geometry maintenance " << endl;
	 
	 
		  
		 
	 
	 }
		   
		   // update the TAF
		   
		   TIC();
		   UpdateGlobalTAF();
		   TOC();
		   cout << StopwatchValue() << " seconds for TAF update" << endl;
 
  // if we're at a save point, then do it!
  
  if( fabs( t - NextOutputTime ) < 1e-6 || fabs( t ) < 1e-6 )
  {
   cout << "Saving data ... " << endl;
   t = NextOutputTime;

   WriteTumorConfigurationFile( t );
   SaveTumorData( t );
   SaveVariables(SaveDirectory,t);

   NextOutputTime += OutputInterval;
  }


     Area_Output.open ("Radius.txt",ios::app);
	
 Area_Output<<Output_Radius(Phi)<<" ";

 //Area_Output<<1<<" ";

 Area_Output.close();
 extern double waterpressureA;
 extern double vesselpressureA;
 extern double hompressureA;
 
      WaterP.open ("WaterP.txt",ios::app);
	
 WaterP<<waterpressureA<<" ";
 
 WaterP.close();
 
  VesselP.open ("VesselP.txt",ios::app);
	
 VesselP<<vesselpressureA<<" ";
 
 VesselP.close();
 
 HomP.open ("HomP.txt",ios::app);
	
 HomP<<hompressureA<<" ";
 
 HomP.close();

  QuickPlot();
  
 }
 
 RUNTIME_TOC();
    
 
 StartStringBuffer( "Finished running simulation.\n" );
 AddToStringBuffer( "total run time: " );
 FormatStopwatchValue( StringBuffer+strlen(StringBuffer) , RuntimeStopwatchValue() );
 cout << StringBuffer << endl;
 MakeLogEntry( LogFile, StringBuffer );  
 
 
 return 0;
}

bool CreateInitialProgramMessage( void )
{
 time_t rawtime;
 struct tm * timeinfo;
 time( &rawtime );
 timeinfo = localtime ( &rawtime ); 
 
 StringBuffer[0] = '\0';

 sprintf( StringBuffer , "Overall version: %s\n Driver version: %s\n  Angio version: %s\n  Tumor version: %s\nCompile time:   %s  %s\nCompiler:       %s\nrun time:       %s",Program_Version,DriverProgram_Version, Angio_Version, TumorGrowth_Version, __DATE__, __TIME__, __COMPILER__, asctime(timeinfo) );
 return true;
}
